package cloud.xlh.service.impl;

import cloud.xlh.exceptionhandle.service.impl.BusinessExceptionEnum;
import cloud.xlh.infrastructure.cache.redis.utils.RedisUtil;
import cloud.xlh.service.IdempotentHandleService;
import cloud.xlh.service.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Service;

/**
 * Created with IntelliJ IDEA.
 *
 * @ project name : xlh_osms
 * @ Author: XuLeHuang
 * @ Date: 2023/1/16 15:47
 * @ Description:
 */
@Service
public class IdempotentHandleServiceImpl implements IdempotentHandleService {
    @Value("${spring.application.name}")
    private String applicationName;

    private static final String spilt = "-";

    @Autowired
    private TokenService tokenService;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public boolean idempotentHandle(ServerHttpRequest request) {
        //同一个请求编号只能一次请求
        String idempotentKey = getIdempotentKey(request);
        if (redisUtil.exist(idempotentKey) && !"OK".equals(redisUtil.get(idempotentKey))) {
            throw BusinessExceptionEnum.DUPLICATEREQUEST.newException();
        } else {
            /**
             * 第一次访问就会生成一条幂等表记录
             * 引入客户端IP是为了减少来自不同客户端重复key误删的概率*/
            redisUtil.set(idempotentKey, "PROC", 10L);
        }
        return true;
    }
    /**
     * 获取幂等性key
     */
    public String getIdempotentKey(ServerHttpRequest request) {
        String token = tokenService.getToken(request);
        String clientIpAddress = request.getRemoteAddress().getAddress().getAddress().toString();
        //String clientIpAddress = CommonUtil.getIpAdrress(request);
        StringBuilder idempotentKey = new StringBuilder(applicationName + spilt + token + spilt + clientIpAddress);
        return idempotentKey.toString();
    }

    /**
     * 标注了@Idempotent注解的方法，响应的时候就会到这里
     */
    @Override
    public void updateIdempotentKey(ServerHttpRequest request) {
        String token = tokenService.getToken(request);
        BusinessExceptionEnum.TOKENNOTEXIST.assertStrNotNull(token);
        String idempotentKey = getIdempotentKey(request);
        redisUtil.set(idempotentKey, "OK", 30L);
    }
}
